home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_unix / j109lxa4.tar / cmdparse.c < prev    next >
C/C++ Source or Header  |  1994-06-04  |  10KB  |  502 lines

  1. /* Parse command line, set up command arguments Unix-style, and call function.
  2.  * Note: argument is modified (delimiters are overwritten with nulls)
  3.  *
  4.  * Copyright 1991 Phil Karn, KA9Q
  5.  *
  6.  * Improved error handling by Brian Boesch of Stanford University
  7.  * Feb '91 - Bill Simpson
  8.  *              bit16cmd for PPP
  9.  * Mar '91 - Glenn McGregor
  10.  *              handle string escaped sequences
  11.  */
  12. #include <stdio.h>
  13. #include <ctype.h>
  14. #ifdef MSDOS
  15. #include <conio.h>
  16. #endif
  17. #include "global.h"
  18. #include "config.h"
  19. #include "proc.h"
  20. #include "cmdparse.h"
  21. #include "session.h"
  22. #include "pktdrvr.h"
  23. #include "iface.h"
  24. #include "socket.h"
  25.  
  26. struct boolcmd {
  27.     char *str;      /* Token */
  28.     int val;        /* Value */
  29. };
  30.  
  31. static struct boolcmd Boolcmds[] = {
  32.     "y",            1,      /* Synonyms for "true" */
  33.     "yes",          1,
  34.     "true",         1,
  35.     "on",           1,
  36.     "1",            1,
  37.     "set",          1,
  38.     "enable",       1,
  39.  
  40.     "n",            0,      /* Synonyms for "false" */
  41.     "no",           0,
  42.     "false",        0,
  43.     "off",          0,
  44.     "0",            0,
  45.     "clear",        0,
  46.     "disable",      0,
  47.     NULLCHAR
  48. };
  49.  
  50. static char *stringparse __ARGS((char *line));
  51.  
  52. static char *
  53. stringparse(line)
  54. char *line;
  55. {
  56.     register char *cp = line;
  57.     unsigned long num;
  58.  
  59.     while ( *line != '\0' && *line != '\"' ) {
  60.         if ( *line == '\\' ) {
  61.             line++;
  62.             switch ( *line++ ) {
  63.             case 'n':
  64.                 *cp++ = '\n';
  65.                 break;
  66.             case 't':
  67.                 *cp++ = '\t';
  68.                 break;
  69.             case 'v':
  70.                 *cp++ = '\v';
  71.                 break;
  72.             case 'b':
  73.                 *cp++ = '\b';
  74.                 break;
  75.             case 'r':
  76.                 *cp++ = '\r';
  77.                 break;
  78.             case 'f':
  79.                 *cp++ = '\f';
  80.                 break;
  81.             case 'a':
  82. #ifdef __STDC__
  83.                 *cp++ = '\a';
  84. #else
  85.                 *cp++ = '\007';
  86. #endif
  87.                 break;
  88.             case '\\':
  89.                 *cp++ = '\\';
  90.                 break;
  91.             case '\?':
  92.                 *cp++ = '\?';
  93.                 break;
  94.             case '\'':
  95.                 *cp++ = '\'';
  96.                 break;
  97.             case '\"':
  98.                 *cp++ = '\"';
  99.                 break;
  100.             case 'x':
  101.                 num = strtoul( --line, &line, 16 );
  102.                 *cp++ = (char) num;
  103.                 break;
  104.             case '0':
  105.             case '1':
  106.             case '2':
  107.             case '3':
  108.             case '4':
  109.             case '5':
  110.             case '6':
  111.             case '7':
  112.                 num = strtoul( --line, &line, 8 );
  113.                 *cp++ = (char) num;
  114.                 break;
  115.             case '\0':
  116.                 return NULLCHAR;
  117.             default:
  118.                 *cp++ = *(line - 1);
  119.                 break;
  120.             };
  121.         } else {
  122.             *cp++ = *line++;
  123.         }
  124.     }
  125.  
  126.     if ( *line == '\"' )
  127.         line++;         /* skip final quote */
  128.     *cp = '\0';             /* terminate string */
  129.     return line;
  130. }
  131.  
  132. #ifdef LOCK
  133. int Kblocked;
  134. char *Kbpasswd;
  135. #endif
  136.  
  137. int
  138. cmdparse(cmds,line,p)
  139. struct cmds cmds[];
  140. register char *line;
  141. void *p;
  142. {
  143.     struct cmds *cmdp;
  144.     char *argv[NARG],*cp;
  145.     char **pargv;
  146.     int argc,i;
  147.  
  148.     /* Remove cr/lf */
  149.     rip(line);
  150.  
  151.     for(argc = 0;argc < NARG;argc++)
  152.         argv[argc] = NULLCHAR;
  153.  
  154.     for(argc = 0;argc < NARG;){
  155.         register int qflag = FALSE;
  156.  
  157.         /* Skip leading white space */
  158.         while(*line == ' ' || *line == '\t')
  159.             line++;
  160.         if(*line == '\0')
  161.             break;
  162.         /* return if comment character first non-white */
  163.         if ( argc == 0  &&  *line == '#' )
  164.             return 0;
  165.         /* Check for quoted token */
  166.         if(*line == '"'){
  167.             line++; /* Suppress quote */
  168.             qflag = TRUE;
  169.         }
  170.         argv[argc++] = line;    /* Beginning of token */
  171.  
  172.         if(qflag){
  173.             /* Find terminating delimiter */
  174.             if((line = stringparse(line)) == NULLCHAR){
  175.                 return -1;
  176.             }
  177.         } else {
  178.             /* Find space or tab. If not present,
  179.              * then we've already found the last
  180.              * token.
  181.              */
  182. #ifdef old
  183.         if((cp = strchr(line,' ')) == NULLCHAR
  184.              && (cp = strchr(line,'\t')) == NULLCHAR){
  185.                 break;
  186.             }
  187. #endif
  188.         for(cp=line;*cp;cp++) {
  189.         if(*cp == ' ' || *cp == '\t')
  190.             break;
  191.         }
  192.         /* if we didn't reach end of line yet, cutoff this arg here */
  193.         if(*cp == '\0')
  194.         break;
  195.         *cp++ = '\0';
  196.             line = cp;
  197.         }
  198.     }
  199.     if (argc < 1) {         /* empty command line */
  200.         argc = 1;
  201.         argv[0] = "";
  202.     }
  203.  
  204. #ifdef LOCK
  205.     /* Check to see if this is the Command session.
  206.      * If so, check to see if the keyboard is locked
  207.      * Added 12/12/91 WG7J
  208.      */
  209.     if(Curproc->input == Command->input)
  210.     if(Kblocked) { /*check argv[0] for password!*/
  211.         if(strcmp(argv[0],Kbpasswd)) {
  212.         tputs("\nKeyboard remains locked\n");
  213.         return 0;
  214.         }
  215.         Command->ttystate.echo = 1; /* turn character echo back on ! */
  216.         Kblocked=0;   /* correct password, so unlock */
  217.         return 0;
  218.     }
  219. #endif
  220.  
  221.     /* Look up command in table; prefix matches are OK */
  222.     /* Not case sensitive anymore - WG7J */
  223.     for(cmdp = cmds;cmdp->name != NULLCHAR;cmdp++){
  224.     if(strncmpi(argv[0],cmdp->name,strlen(argv[0])) == 0)
  225.             break;
  226.     }
  227.     if(cmdp->name == NULLCHAR) {
  228.         if(cmdp->argc_errmsg != NULLCHAR)
  229.             tprintf("%s\n",cmdp->argc_errmsg);
  230.         return -1;
  231.     } else {
  232.         if(argc < cmdp->argcmin) {
  233.             /* Insufficient arguments */
  234.             tprintf("Usage: %s\n",cmdp->argc_errmsg);
  235.             return -1;
  236.         } else {
  237.             if(cmdp->stksize == 0){
  238.                 return (*cmdp->func)(argc,argv,p);
  239.             } else {
  240.                 /* Make private copy of argv and args,
  241.                  * spawn off subprocess and return.
  242.                  */
  243.                 pargv = (char **)callocw((unsigned)argc,sizeof(char *));
  244.                 for(i=0;i<argc;i++)
  245.                     pargv[i] = strdup(argv[i]);
  246.                 newproc(cmdp->name,(unsigned)cmdp->stksize,
  247.                 (void (*)__ARGS((int,void*,void*)))cmdp->func,argc,pargv,p,1);
  248.                 return(0);
  249.             }
  250.         }
  251.     }
  252. }
  253.  
  254. /* Call a subcommand based on the first token in an already-parsed line */
  255. int
  256. subcmd(tab,argc,argv,p)
  257. struct cmds tab[];
  258. int argc;
  259. char *argv[];
  260. void *p;
  261. {
  262.     register struct cmds *cmdp;
  263.     char **pargv;
  264.     int found = 0;
  265.     int i;
  266.  
  267.     /* Strip off first token and pass rest of line to subcommand */
  268.     if (argc < 2) {
  269.         if (argc < 1)
  270.             tprintf("SUBCMD - Don't know what to do?\n");
  271.         else
  272.             tprintf("\"%s\" - takes at least one argument\n",argv[0]);
  273.         return -1;
  274.     }
  275.     argc--;
  276.     argv++;
  277.     for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++){
  278.     /* Not case sensitive anymore - WG7J */
  279.     if(strncmpi(argv[0],cmdp->name,strlen(argv[0])) == 0){
  280.             found = 1;
  281.             break;
  282.         }
  283.     }
  284.     if(!found){
  285.         tprintf("valid subcommands:");
  286.         for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++)
  287.             if(tprintf(" %s",cmdp->name) == EOF)
  288.                 return -1;
  289.         tprintf("\n");
  290.         return -1;
  291.     }
  292.     if(argc < cmdp->argcmin){
  293.         if(cmdp->argc_errmsg != NULLCHAR)
  294.             tprintf("Usage: %s\n",cmdp->argc_errmsg);
  295.         return -1;
  296.     }
  297.     if(cmdp->stksize == 0){
  298.         return (*cmdp->func)(argc,argv,p);
  299.     } else {
  300.         /* Make private copy of argv and args */
  301.         pargv = (char **)callocw((unsigned)argc,sizeof(char *));
  302.         for(i=0;i<argc;i++)
  303.             pargv[i] = strdup(argv[i]);
  304.         newproc(cmdp->name,(unsigned)cmdp->stksize,
  305.          (void (*)__ARGS((int,void*,void*)))cmdp->func,argc,pargv,p,1);
  306.         return(0);
  307.     }
  308. }
  309.  
  310. /* Subroutine for setting and displaying boolean flags */
  311. int
  312. setbool(var,label,argc,argv)
  313. int *var;
  314. char *label;
  315. int argc;
  316. char *argv[];
  317. {
  318.     struct boolcmd *bc;
  319.  
  320.     if(argc < 2){
  321.         tprintf("%s: %s\n",label,*var ? "on":"off");
  322.         return 1;
  323.     }
  324.     for(bc = Boolcmds;bc->str != NULLCHAR;bc++){
  325.         if(strcmpi(argv[1],bc->str) == 0){
  326.             *var = bc->val;
  327.             return 0;
  328.         }
  329.     }
  330.     tprintf("Valid options:");
  331.     for(bc = Boolcmds;bc->str != NULLCHAR;bc++)
  332.         if(tprintf(" %s",bc->str) == EOF)
  333.             return 1;
  334.     tprintf("\n");
  335.     return 1;
  336. }
  337.  
  338.  
  339. /* Subroutine for setting and displaying bit values */
  340. int
  341. bit16cmd(bits,mask,label,argc,argv)
  342. int16 *bits;
  343. int16 mask;
  344. char *label;
  345. int argc;
  346. char *argv[];
  347. {
  348.     int doing = (*bits & mask);
  349.     int result = setbool( &doing, label, argc, argv );
  350.  
  351.     if ( !result ) {
  352.         if ( doing )
  353.             *bits |= mask;
  354.         else
  355.             *bits &= ~mask;
  356.     }
  357.     return result;
  358. }
  359.  
  360.  
  361. /* Subroutine for setting and displaying long variables */
  362. int
  363. setlong(var,label,argc,argv)
  364. long *var;
  365. char *label;
  366. int argc;
  367. char *argv[];
  368. {
  369.     if(argc < 2){
  370.         tprintf("%s: %ld\n",label,*var);
  371.         return 1;
  372.     } else {
  373.         *var = atol(argv[1]);
  374.         return 0;
  375.     }
  376.  
  377. }
  378. /* Subroutine for setting and displaying short variables */
  379. int
  380. setshort(var,label,argc,argv)
  381. unsigned short *var;
  382. char *label;
  383. int argc;
  384. char *argv[];
  385. {
  386.     if(argc < 2){
  387.         tprintf("%s: %u\n",label,*var);
  388.         return 1;
  389.     } else {
  390.         *var = atoi(argv[1]);
  391.         return 0;
  392.     }
  393. }
  394. /* Subroutine for setting and displaying integer variables */
  395. int
  396. setint(var,label,argc,argv)
  397. int *var;
  398. char *label;
  399. int argc;
  400. char *argv[];
  401. {
  402.     if(argc < 2){
  403.         tprintf("%s: %i\n",label,*var);
  404.         return 1;
  405.     } else {
  406.         *var = atoi(argv[1]);
  407.         return 0;
  408.     }
  409.  
  410. }
  411.  
  412. /* Subroutine for setting and displaying unsigned integer variables */
  413. int
  414. setuns(var,label,argc,argv)
  415. unsigned *var;
  416. char *label;
  417. int argc;
  418. char *argv[];
  419. {
  420.     if(argc < 2){
  421.         tprintf("%s: %u\n",label,*var);
  422.         return 1;
  423.     } else {
  424.         *var = atoi(argv[1]);
  425.         return 0;
  426.     }
  427. }
  428.  
  429. /* Subroutine for setting and displaying int variables (with range check) */
  430. int
  431. setintrc(var, label, argc, argv, minval, maxval)
  432. int16 *var;
  433. char *label;
  434. int argc;
  435. char *argv[];
  436. int minval;
  437. int16 maxval;
  438. {
  439.     int tmp;
  440.  
  441.     if (argc < 2)
  442.         tprintf("%s: %u\n", label, *var);
  443.     else {
  444.         tmp = atoi(argv[1]);
  445.         if (isalpha(*argv[1]) || tmp < minval || tmp > maxval) {
  446.             tprintf("%s must be %i..%i\n", label, minval, maxval);
  447.             return 1;
  448.         }
  449.         *var = (int16)tmp;
  450.     }
  451.     return 0;
  452. }
  453.  
  454. /* Set flags on ax.25 interfaces - WG7J */
  455.  
  456. int setflag(int argc,char *ifname,long flag,char *cmd) {
  457. struct iface *ifp;
  458. struct boolcmd *bc;
  459.  
  460.     if(argc == 1) {
  461.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next)
  462.         if(ifp->flags & flag)
  463.         tprintf("%s\n",ifp->name);
  464.     } else {
  465.     if((ifp = if_lookup(ifname)) == NULLIF){
  466.         tprintf(Badinterface,ifname);
  467.         return 1;
  468.     }
  469. /*
  470.     if(ifp->type != CL_AX25) {
  471.         tputs("not an AX.25 interface\n");
  472.         return 1;
  473.     }
  474. */
  475.     if(argc == 2) {
  476.         /* Show the value of the flag */
  477.         if(ifp->flags & flag)
  478.         tputs("On\n");
  479.         else
  480.         tputs("Off\n");
  481.     } else {
  482.         for(bc = Boolcmds;bc->str != NULLCHAR;bc++)
  483.         if(strcmpi(cmd,bc->str) == 0){
  484.             if(bc->val)
  485.             ifp->flags |= flag;
  486.             else
  487.             ifp->flags &= ~flag;
  488.             return 0;
  489.         }
  490.         /* Invalid option ! */
  491.         tputs("Valid options:");
  492.         for(bc = Boolcmds;bc->str != NULLCHAR;bc++)
  493.         if(tprintf(" %s",bc->str) == EOF)
  494.             return 1;
  495.         tputc('\n');
  496.     }
  497.     }
  498.     return 0;
  499. }
  500.  
  501.  
  502.